/*
 * $Id: condition.c,v 1.7 2005-12-26 09:19:46 bacon Exp $
 */

#include <xp/bas/thr.h>
#include <xp/bas/mtx.h>
#include <xp/bas/cond.h>
#include <xp/bas/time.h>
#include <xp/bas/stdio.h>

#ifdef __linux
#include <mcheck.h>
#endif

xp_mtx_t mutex;
xp_cond_t condition;
int dummy1_done = 0;
int dummy2_done = 0;

int dummy (xp_thr_t* thr)
{
	int i;

	for (i = 0; i < 10; i++) {
		xp_mtx_lock (&mutex);
		xp_printf (XP_TEXT("+dummy1. %d\n"), i);
		if (i == 4 || i == 6) xp_sleep (1000);
		dummy1_done = 1;
		xp_cond_signal (&condition);
		xp_mtx_unlock (&mutex);

		xp_mtx_lock (&mutex);
		while (1) {
			if (dummy2_done) {
				dummy2_done = 0;
				break;
			}

			xp_cond_twait (&condition, &mutex, 1000);
			if (!dummy2_done) {
				xp_printf (XP_TEXT("+dummy1. timedout\n"));
			}
		}
		xp_mtx_unlock (&mutex);
	}

	return 0;
}

int dummy2 (xp_thr_t* thr)
{
	int i;

	for (i = 0; i < 10; i++) {
		xp_mtx_lock (&mutex);
		while (1) {
			if (dummy1_done) {
				xp_printf (XP_TEXT("-dummy2. %d\n"), i);
				dummy1_done = 0;
				break;
			}

			xp_cond_twait (&condition, &mutex, 1000);
			if (!dummy1_done) {
				xp_printf (XP_TEXT("-dummy2. timedout\n"));
			}
		}
		xp_mtx_unlock (&mutex);

		xp_mtx_lock (&mutex);
		if (i == 1 || i == 8) xp_sleep (1000);
		dummy2_done = 1;
		xp_cond_signal(&condition);
		xp_mtx_unlock (&mutex);
	}

	return 0;
}

int xp_main ()
{
	xp_thr_t thr1, thr2;

#ifdef __linux
	mtrace ();
#endif
	if (xp_mtx_open (&mutex) == XP_NULL) {
		xp_printf (XP_TEXT("cannot open mutex\n"));
		return -1;
	}

	if (xp_cond_open (&condition) == XP_NULL) {
		xp_printf (XP_TEXT("cannot open mutex\n"));
		return -1;
	}

	if (xp_thr_open (&thr1, dummy, 0) == XP_NULL) {
		xp_printf (XP_TEXT("cannot open thread\n"));
		return -1;
	}
	if (xp_thr_open (&thr2, dummy2, 0) == XP_NULL) {
		xp_printf (XP_TEXT("cannot open thread\n"));
		return -1;
	}

	if (xp_thr_start (&thr1, 0) == -1) {
		xp_printf (XP_TEXT("cannot start thread\n"));
		return -1;
	}
	if (xp_thr_start (&thr2, 0) == -1) {
		xp_printf (XP_TEXT("cannot start thread\n"));
		return -1;
	}

	xp_thr_join (&thr1);
	xp_thr_join (&thr2);
	xp_thr_close (&thr1);
	xp_thr_close (&thr2);

	xp_mtx_close (&mutex);
	xp_cond_close (&condition);

#ifdef __linux
	muntrace ();
#endif

	return 0;
}
